package com.liaogui.web.strategy;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 权重随机数
 * @author liaogui
 * @date 2025/3/1 22:40
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class WeightRandomStrategy implements LotteryStrategy{

    private final RedisTemplate<String, Object> redisTemplate;

    // 预加载提升性能
    private static final DefaultRedisScript<Long> STOCK_SCRIPT = new DefaultRedisScript<>();

    static {
        STOCK_SCRIPT.setScriptSource(new ResourceScriptSource(new ClassPathResource("stock.lua")));
        STOCK_SCRIPT.setResultType(Long.class);
    }
    @Override
    public Map<Object, Object> drawPrize(Map<String, Map<Object, Object>> map) {
        // 总权重
        int totalWeight = 0;
        List<String> prizeIds = new ArrayList<>();
        List<Integer> weights = new ArrayList<>();
        for (Map.Entry<String, Map<Object, Object>> entry : map.entrySet()) {
            totalWeight += Integer.parseInt(entry.getValue().get("prizeWeight").toString());
            prizeIds.add(entry.getKey());
            weights.add(totalWeight);
        }

        // 随机数
        int random = ThreadLocalRandom.current().nextInt(totalWeight);
        // 改造一下
        int sum = 0;
        for (String prizeId : prizeIds) {
            Map<Object, Object> prizeMap = map.get(prizeId);
            int prizeWeight = (int)prizeMap.get("prizeWeight");
            if (prizeWeight > 0 ){
                sum += prizeWeight;
                if (sum >= random) {
                    boolean flag = deductStock(prizeMap);
                    if (!flag){
                        continue;
                    }
                    return prizeMap;
                }
            }
        }

        Map<Object, Object> losingLotteryMap = new HashMap<>();
        losingLotteryMap.put("prizeId", "PRIZE_LOSING");
        losingLotteryMap.put("prizeName", "谢谢惠顾");
        losingLotteryMap.put("prizeDesc", "未中奖");
        losingLotteryMap.put("prizeValue", 0);
        losingLotteryMap.put("prizeStatus", "prize_losing");
        return losingLotteryMap;
    }

    // 扣除库存
    public boolean deductStock(Map<Object, Object> prizeInfo) {
        // 扣减库存 redis原子操作
        String key = "DRAW:PRIZE:ACT202502281645:" + prizeInfo.get("prizeId");

        Long result = redisTemplate.execute(
                STOCK_SCRIPT,
                Arrays.asList(key, "prizeValue"),
                1
        );
        if (result != null && result >= 0) {
            log.info("库存扣减成功");
            return true;
        }

        if (result == -1) {
            log.error("库存不足");
        }
        return false;
    }

}
